#include "stdafx.h"
#include "servicelisten.h"
#ifdef _DEBUG
	#undef THIS_FILE
	static char THIS_FILE[] = __FILE__;
	#undef DEBUG_NEW
	#define	DEBUG_NEW new(_NORMAL_BLOCK,__FILE__,__LINE__)
	#define new DEBUG_NEW
#endif
/////////////////////////////////////////////////////////////////////////////
service_listen::service_listen(void):
	_pservice(NULL),srvSocket(INVALID_SOCKET),_pfcreate(NULL),
	list_normal(NULL),list_recycle(NULL),list_doing(NULL)
{
}

service_listen::~service_listen(void)
{
}
/////////////////////////////////////////////////////////////////////////////
BOOL service_listen::create(long port_listen,LPTSTR strError)
{
	do
	{
		sockaddr_in	addr={0};
#ifdef	WIN32
		if((srvSocket=socket(PF_INET,SOCK_STREAM,0))==INVALID_SOCKET)
#else
		if((srvSocket=socket(PF_INET,SOCK_STREAM,0))<0)
#endif
		{
			srvSocket = INVALID_SOCKET;
			wsprintf(strError,TEXT("socket() error:%d"),WSA_LAST_ERROR);
			break;
		}
		addr.sin_family = AF_INET;
		addr.sin_addr.s_addr = htonl(INADDR_ANY);
		addr.sin_port = htons((WORD)port_listen);

#ifdef	WIN32
		if(bind(srvSocket,(PSOCKADDR)&addr,sizeof(addr))==SOCKET_ERROR)
#else
		if(bind(srvSocket,(sockaddr*)&addr,sizeof(addr)))
#endif
		{
			wsprintf(strError,TEXT("bind() error:%d,%d"),port_listen,WSA_LAST_ERROR);
			break;
		}
		listen(srvSocket,8);
		if(!zwl_thread::create_main(strError,TRUE)) break;
		return(TRUE);
	}while(0);
	CLOSE_SOCKET(srvSocket);
	return(FALSE);
}

static __int64 __id_control__(0);
void service_listen::createcontrol(SOCKET hSocket,LPCTSTR lpAddress)
{
	zwl_srv_control*pcontrol=list_recycle->get();
	if(!pcontrol) pcontrol=_pfcreate(_pservice);
	if(pcontrol)
	{
		pcontrol->cltSocket = hSocket;
		pcontrol->idControl = ++__id_control__;
		if(pcontrol->on_connect(_pservice))
		{
			lstrcpy(pcontrol->logon_ipv4,lpAddress);
			_pservice->online_addnew(pcontrol);
			list_normal->add_job(pcontrol);
		}
		else
		{
			pcontrol->shutdown();
			list_doing->add_job(pcontrol);
		}
	}
	else
	{
		closesocket(hSocket);
	}
}

void service_listen::destory(void)
{
	runMode = 0;
	CLOSE_SOCKET(srvSocket);
	zwl_thread::destory_main();
}

void service_listen::main(void)
{
	sockaddr_in	addr={0};
	socklen_t naddr(0);
	long noDelay=0,tmSend=0,tmRecv=0;
	SOCKET hSocket(INVALID_SOCKET);
	BYTE ipaddr[4]={0};
	TCHAR ipv4_address[64]={0};
	while(runMode)
	{
		noDelay=1,tmSend=tmRecv=15000L;
		memset(&addr,0,naddr=sizeof(sockaddr_in));
#ifdef	WIN32
		if((hSocket=accept(srvSocket,(SOCKADDR*)&addr,&naddr))==INVALID_SOCKET) continue;
		setsockopt(hSocket,IPPROTO_TCP,TCP_NODELAY,(LPSTR)&noDelay,sizeof(long));
#else
		if((hSocket=accept(srvSocket,(sockaddr*)&addr,&naddr))<0) continue;
#endif
		setsockopt(hSocket,SOL_SOCKET,SO_SNDTIMEO,(LPSTR)&tmSend,sizeof(long));
		setsockopt(hSocket,SOL_SOCKET,SO_RCVTIMEO,(LPSTR)&tmRecv,sizeof(long));
		
		memcpy(ipaddr,&addr.sin_addr,4);
		wsprintf(ipv4_address,TEXT("%d.%d.%d.%d"),ipaddr[0],ipaddr[1],ipaddr[2],ipaddr[3]);

		createcontrol(hSocket,ipv4_address);
	}
}
